﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mls
{

    public static class CharactersMapper
    {
        public static string Map(Character character)
        {
            string map = string.Empty;

            if (character.Language.IsArabic)
                map = MapArabic(character.Raw);
            else if (character.Language.IsLatin)
                map = MapLatin(character.Raw);
            else if (character.Language.IsCoptic)
                map = MapCoptic(character.Raw);
            else if (character.Language.IsGreek)
                map = MapGreek(character.Raw);
            else
                throw new InvalidOperationException();

            if (character.IsAccented)
            {
                foreach (byte id in character.Accents.AccentIds)
                {
                    if (character.Language.IsArabic)
                        map += MapArabicAccent(id);
                    else if (character.Language.IsLatin)
                        map += MapLatinAccent(id);
                    else if (character.Language.IsCoptic)
                        map += MapCopticAccent(id);
                    else if (character.Language.IsGreek)
                        map += MapGreekAccent(id);
                    else
                        throw new InvalidOperationException();
                }
            }

            return map;
        }

        private static string MapLatinAccent(byte accentId) { return MapLatin(AccentsMap[accentId - 1]); }
        private static string MapCopticAccent(byte accentId) { return MapCoptic(AccentsMap[accentId - 1]); }
        private static string MapArabicAccent(byte accentId) { return MapArabic(AccentsMap[accentId - 1]); }
        private static string MapGreekAccent(byte accentId) { return MapGreek(AccentsMap[accentId - 1]); }

        private const byte LatinSupportedCharactersLowLimit = 0x20;
        private const byte LatinSupportedCharactersHighLimit = 0x7E;
        private static Dictionary<byte, string> _latinMap = new Dictionary<byte, string>();
        private static Dictionary<byte, string> _arabicMap = new Dictionary<byte, string>();
        private static Dictionary<byte, string> _copticMap = new Dictionary<byte, string>();
        private static Dictionary<byte, string> _greekMap = new Dictionary<byte, string>();

        private static string MapLatin(byte raw)
        {
            if (_latinMap.ContainsKey(raw))
                return _latinMap[raw];
            if (raw >= LatinSupportedCharactersLowLimit && raw <= LatinSupportedCharactersHighLimit)
                return ((char)raw).ToString();

            return "?";//throw new UnknownCharacterException(raw, "Latin");
        }
        private static string MapArabic(byte raw)
        {
            if (!_arabicMap.ContainsKey(raw))
                return "?";//throw new UnknownCharacterException(raw, "Arabic");
            return _arabicMap[raw];
        }
        private static string MapCoptic(byte raw)
        {
            if (!_copticMap.ContainsKey(raw))
                return "?";//throw new UnknownCharacterException(raw, "Coptic");
            return _copticMap[raw];
        }
        private static string MapGreek(byte raw)
        {
            if (!_greekMap.ContainsKey(raw))
                return "?";//throw new UnknownCharacterException(raw, "Greek");
            return _greekMap[raw];
        }

        // Accents map for codes from 1 to 31 -> Maps to raw code in each language
        private static byte[] AccentsMap = new byte[] {
	        0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,
	        0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,
            0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xB6,0xB7,0xB8
        };

        static CharactersMapper()
        {
            // Latin Map

            _latinMap.Add(0x80, "\r\n");

            _latinMap.Add(0x81, "\xBF");
            _latinMap.Add(0x82, "\xD6");
            _latinMap.Add(0x83, "\x152");
            _latinMap.Add(0x84, "\xDC");
            _latinMap.Add(0x85, "\x162");
            _latinMap.Add(0x86, "\xC4");
            _latinMap.Add(0x87, "\x170");
            _latinMap.Add(0x88, "\x130");
            _latinMap.Add(0x89, "\xD8");
            _latinMap.Add(0x8A, "\xA3");
            _latinMap.Add(0x8F, "\xC6");

            _latinMap.Add(0x90, "\x15E");
            _latinMap.Add(0x91, "\x110");
            _latinMap.Add(0x92, "\x150");
            _latinMap.Add(0x93, "\x104");
            _latinMap.Add(0x94, "Ch");
            _latinMap.Add(0x95, "\x118");
            _latinMap.Add(0x96, "Ll");
            _latinMap.Add(0x97, "\x2C62");
            _latinMap.Add(0x9E, "\xDE");
            _latinMap.Add(0x9F, "\xC7");

            _latinMap.Add(0xA1, "\xDF");
            _latinMap.Add(0xA2, "\xD1");
            _latinMap.Add(0xA4, "\x323"); //[Accent] Dot below
            _latinMap.Add(0xA5, "\x324"); //[Accent] Two dots below
            _latinMap.Add(0xA6, "\x325"); //[Accent] Circle Below
            _latinMap.Add(0xA7, "\x35A"); //[Accent] Two circles below
            _latinMap.Add(0xA8, "\x331"); //[Accent] Underscore
            _latinMap.Add(0xA9, "\x329"); //[Accent] Vertical line below
            _latinMap.Add(0xAC, "\x301"); //[Accent] Acute accent
            _latinMap.Add(0xAD, "\x300"); //[Accent] Grave accent
            _latinMap.Add(0xAE, "\x308"); //[Accent] Double dots above
            _latinMap.Add(0xAF, "\x303"); //[Accent] Tilde

            _latinMap.Add(0xB0, "\x302"); //[Accent] Circumflex accent
            _latinMap.Add(0xB1, "\x306"); //[Accent] Breve
            _latinMap.Add(0xB2, "\x30A"); //[Accent] Circle above
            _latinMap.Add(0xB3, "\x30C"); //[Accent] Caron
            _latinMap.Add(0xB4, "\x304"); //[Accent] Macron
            _latinMap.Add(0xB5, "\x307"); //[Accent] Dot above

            // Repeated Accents for capital letters
            _latinMap.Add(0xC5, "\x301"); //[Accent] Acute accent
            _latinMap.Add(0xC6, "\x300"); //[Accent] Grave accent
            _latinMap.Add(0xC7, "\x308"); //[Accent] Double dots above
            _latinMap.Add(0xC8, "\x303"); //[Accent] Tilde
            _latinMap.Add(0xC9, "\x302"); //[Accent] Circumflex accent
            _latinMap.Add(0xCA, "\x306"); //[Accent] Breve
            _latinMap.Add(0xCB, "\x30A"); //[Accent] Circle above
            _latinMap.Add(0xCC, "\x30C"); //[Accent] Caron
            _latinMap.Add(0xCD, "\x304"); //[Accent] Macron
            _latinMap.Add(0xCE, "\x307"); //[Accent] Dot above

            _latinMap.Add(0xE9, "\xA1");
            _latinMap.Add(0xEA, "\xB6");
            _latinMap.Add(0xEB, "\xA7");
            _latinMap.Add(0xEC, "\x2020");
            _latinMap.Add(0xED, "\x2A0D");
            _latinMap.Add(0xEE, "\xAE");
            _latinMap.Add(0xEF, "\xA9");

            _latinMap.Add(0xF0, "\x21A9"); // Couldn't find similar arrow
            _latinMap.Add(0xF1, "\xAB");
            _latinMap.Add(0xF2, "\xBB");
            _latinMap.Add(0xF3, "\x2122");
            _latinMap.Add(0xF5, ""); // Reverse Indent
            _latinMap.Add(0xFA, "/"); // Embed
            _latinMap.Add(0xFB, "|"); // Delimiter
            _latinMap.Add(0xFC, "\xA0"); // Hard space
            _latinMap.Add(0xFD, "\x200B"); // Zero width space

            // Arabic Map

            _arabicMap.Add(0x01, "\xF7"); // Division
            _arabicMap.Add(0x19, ")"); // Brackets
            _arabicMap.Add(0x1A, "("); // Brackets
            _arabicMap.Add(0x1B, "[1B?]"); // UNKNOWN ????

            _arabicMap.Add(0x20, "\x20"); // Space
            _arabicMap.Add(0x21, "\x61F"); // Arabic question mark
            _arabicMap.Add(0x22, "\x21"); // Execlimation mark
            _arabicMap.Add(0x23, "\x23"); // Brackets
            _arabicMap.Add(0x24, "\x24");
            _arabicMap.Add(0x25, "\xBB"); // Double angle brackets
            _arabicMap.Add(0x26, "\xAB"); // Double angle brackets
            _arabicMap.Add(0x27, "\x66A"); // Arabic Percentage
            _arabicMap.Add(0x2B, "\x686"); // TCHEH*
            _arabicMap.Add(0x2C, "\x60C"); // Arabic comma
            _arabicMap.Add(0x2D, "\x6AF"); // Persian GAF
            _arabicMap.Add(0x2E, "\x2E"); // Period
            _arabicMap.Add(0x2F, "\x6F4"); // Persian

            _arabicMap.Add(0x30, "\x660"); // Zero
            _arabicMap.Add(0x31, "\x661");
            _arabicMap.Add(0x32, "\x662");
            _arabicMap.Add(0x33, "\x663");
            _arabicMap.Add(0x34, "\x664");
            _arabicMap.Add(0x35, "\x665");
            _arabicMap.Add(0x36, "\x666");
            _arabicMap.Add(0x37, "\x667");
            _arabicMap.Add(0x38, "\x668");
            _arabicMap.Add(0x39, "\x669"); // Nine
            _arabicMap.Add(0x3A, "\x3A"); // Period
            _arabicMap.Add(0x3B, "\x61B"); // Arabic semi-colon
            _arabicMap.Add(0x3C, "\x6F5"); // Persian
            _arabicMap.Add(0x3D, "[??]"); // Persian Letter not found in UNICODE
            _arabicMap.Add(0x3E, "\x67E"); // PHEH
            _arabicMap.Add(0x3F, "\x686"); // TCHEH*

            _arabicMap.Add(0x40, "\x698"); // JEH*
            _arabicMap.Add(0x41, "\x627"); // ALEF MAD
            _arabicMap.Add(0x42, "\x628"); // BEH
            _arabicMap.Add(0x43, "\x62A"); // TEH
            _arabicMap.Add(0x44, "\x62B"); // THEH
            _arabicMap.Add(0x45, "\x62C"); // GEEM
            _arabicMap.Add(0x46, "\x62D"); // HAH
            _arabicMap.Add(0x47, "\x62E"); // KHAH
            _arabicMap.Add(0x48, "\x62F"); // DAL
            _arabicMap.Add(0x49, "\x630"); // DHAL
            _arabicMap.Add(0x4A, "\x631"); // REH
            _arabicMap.Add(0x4B, "\x632"); // ZEN
            _arabicMap.Add(0x4C, "\x633"); // SEEN
            _arabicMap.Add(0x4D, "\x634"); // SHEEN
            _arabicMap.Add(0x4E, "\x635"); // SAD
            _arabicMap.Add(0x4F, "\x636"); // DAD

            _arabicMap.Add(0x50, "\x637"); // TAH
            _arabicMap.Add(0x51, "\x638"); // DHAH
            _arabicMap.Add(0x52, "\x639"); // EN
            _arabicMap.Add(0x53, "\x63A"); // GHEN
            _arabicMap.Add(0x54, "\x641"); // FEH 
            _arabicMap.Add(0x55, "\x642"); // QAF
            _arabicMap.Add(0x56, "\x643"); // KAF
            _arabicMap.Add(0x57, "\x644"); // LAM
            _arabicMap.Add(0x58, "\x645"); // MEEM
            _arabicMap.Add(0x59, "\x646"); // NOON
            _arabicMap.Add(0x5A, "\x648"); // WAW
            _arabicMap.Add(0x5B, "\x647"); // HEH
            _arabicMap.Add(0x5C, "\x629"); // TEH MARBOOTA
            _arabicMap.Add(0x5D, "\x64A"); // YEH
            _arabicMap.Add(0x5E, "\x649"); // YEH LAYENA
            _arabicMap.Add(0x5F, "\x640"); // TATWEEL

            _arabicMap.Add(0x60, "\x621"); // HAMZA ALA EL SATR
            _arabicMap.Add(0x61, "\x623"); // ALEF HAMZA
            _arabicMap.Add(0x62, "\x625"); // ALEF HAMZA KASR
            _arabicMap.Add(0x63, "\x627\x64B"); // ALEF TANWIIN
            _arabicMap.Add(0x64, "\x622"); // ALEF MAD
            _arabicMap.Add(0x65, "\x626"); // HAMZA ALA NABRA
            _arabicMap.Add(0x66, "\x624"); // HAMZA ALA WAW
            _arabicMap.Add(0x67, "\x644\x627"); // LAM ALEF
            _arabicMap.Add(0x68, "\x644\x623");
            _arabicMap.Add(0x69, "\x644\x625");
            _arabicMap.Add(0x6A, "\x644\x622");
            _arabicMap.Add(0x6B, "\x644\x644\x647"); // LELAH
            _arabicMap.Add(0x6C, "\x640"); // TATWEEL
            _arabicMap.Add(0x6D, "\x6AF"); // GAF with fat-ha ??
            _arabicMap.Add(0x6E, "\x6C0"); // HEH + HAMZA
            _arabicMap.Add(0x6F, "\x6AF"); // GAF with fat-ha ??

            _arabicMap.Add(0x70, "\x6AF"); // GAF with fat-ha ??
            _arabicMap.Add(0x71, "\x6AF"); // GAF with fat-ha ??
            _arabicMap.Add(0x72, "\x671"); // ALEF + WASL

            _arabicMap.Add(0x80, "\r\n"); // New line

            _arabicMap.Add(0x97, "\x698"); // JEH ?? 
            _arabicMap.Add(0x9D, "\x686"); // TCHEH ??
            _arabicMap.Add(0x9E, "\x629"); // TEH MARBOOTA ??

            _arabicMap.Add(0xAC, "\x64E"); // [Accent] FAT-HA
            _arabicMap.Add(0xAD, "\x64F"); // [Accent] DAMMA
            _arabicMap.Add(0xAE, "\x650"); // [Accent] KASRA
            _arabicMap.Add(0xAF, "\x652"); // [Accent] SOKON
            _arabicMap.Add(0xB0, "\x64B"); // [Accent] FAT-HETEN
            _arabicMap.Add(0xB1, "\x64C"); // [Accent] DAMMETEN
            _arabicMap.Add(0xB2, "\x64D"); // [Accent] KASRETEN
            _arabicMap.Add(0xB3, "\x651"); // [Accent] SHADDA
            _arabicMap.Add(0xB4, "\x651\x64E"); // [Accent] SHADDA + FAT-HA
            _arabicMap.Add(0xB5, "\x651\x64F"); // [Accent] SHADDA + DAMMA

            _arabicMap.Add(0xC5, "\x651\x650"); // [Accent] SHADDA + KASRA
            _arabicMap.Add(0xC6, "\x651\x64B"); // [Accent] SHADDA + FAT-HETER
            _arabicMap.Add(0xC7, "\x651\x64C"); // [Accent] SHADDA + DAMETEN
            _arabicMap.Add(0xC8, "\x651\x64D"); // [Accent] SHADDA + KASRETER
            _arabicMap.Add(0xC9, "\x670"); // [Accent] ALEF MAD
            _arabicMap.Add(0xCB, "\x650"); // [Accent] KASRA

            _arabicMap.Add(0xEB, "\x67E"); // PEH*

            _arabicMap.Add(0xF5, ""); // Reverse Indent
            _arabicMap.Add(0xFA, "/"); // Embed
            _arabicMap.Add(0xFB, "|"); // Delimiter
            _arabicMap.Add(0xFC, "\xA0"); // Hard space
            _arabicMap.Add(0xFD, "\x200B"); // Zero width space

            // Coptic Map

            _copticMap.Add(0x01, "\x2719"); // Cross
            _copticMap.Add(0x02, "\x2725"); // Cross
            _copticMap.Add(0x0F, "\x2CEA"); // GSHEMA OMECRON in EBSHOIC

            _copticMap.Add(0x16, "[16?]"); // UNKNOWN ????
            _copticMap.Add(0x17, "\x271B"); // Cross
            _copticMap.Add(0x18, "[18?]"); // UNKNOWN ????

            _copticMap.Add(0x20, "\x20"); // Space
            _copticMap.Add(0x21, "\x2CA3\x304"); //r
            _copticMap.Add(0x22, "\x2CAE"); // EBSI
            _copticMap.Add(0x23, "\x2CA7\x304"); //t
            _copticMap.Add(0x24, "\x2CA9\x304"); //u
            _copticMap.Add(0x25, "\x2CAB\x304"); //v
            _copticMap.Add(0x26, "\x2CAF\x304"); // EBSI Number
            _copticMap.Add(0x27, "\x2CAF"); // EBSI SMALL
            _copticMap.Add(0x28, "\x28"); // '(' Remain the same
            _copticMap.Add(0x29, "\x29"); // ')' Remain the same
            _copticMap.Add(0x2A, "\x2A"); // '*' Remain the same
            _copticMap.Add(0x2B, "\x2CE7"); // Stawros
            _copticMap.Add(0x2C, "\x2CAD"); // KI
            _copticMap.Add(0x2D, "\x2D"); // '-' Remain the same
            _copticMap.Add(0x2E, "\x2E"); //'.'
            _copticMap.Add(0x2F, "\x2C8F"); // HADA SMALL

            _copticMap.Add(0x31, "\x2C81\x304"); //Alpha Number
            _copticMap.Add(0x32, "\x2C83\x304"); //Beta Number
            _copticMap.Add(0x33, "\x2C85\x304"); //Gamma Number
            _copticMap.Add(0x34, "\x2C87\x304"); //Delta Number
            _copticMap.Add(0x35, "\x2C89\x304"); //Ayya Number
            _copticMap.Add(0x36, "\x2C8B\x304"); //Soo Number
            _copticMap.Add(0x37, "\x2C8D\x304"); //Zada Number
            _copticMap.Add(0x38, "\x2C8F\x304"); //Hada Number
            _copticMap.Add(0x39, "\x2C91\x304"); //Tetta Number
            _copticMap.Add(0x3A, ":"); //':'
            _copticMap.Add(0x3B, "\x2C93\x304"); // YODA NUMBER
            _copticMap.Add(0x3C, "\x2CAC"); // KI
            _copticMap.Add(0x3D, "\x2CE5"); // Martiros
            _copticMap.Add(0x3E, "\x2CAC"); // KI
            _copticMap.Add(0x3F, "\x2C8E"); // HADA

            _copticMap.Add(0x40, "\x2CA5\x304"); //c
            _copticMap.Add(0x41, "\x2C80"); // ALPHA
            _copticMap.Add(0x42, "\x2C82"); // BETA
            _copticMap.Add(0x43, "\x2CA4"); // CEEMA
            _copticMap.Add(0x44, "\x2C86"); // DELTA
            _copticMap.Add(0x45, "\x2C88"); // AYYA
            _copticMap.Add(0x46, "\x3E4"); // FAI
            _copticMap.Add(0x47, "\x2C84"); // GHAMA
            _copticMap.Add(0x48, "\x3E8"); // HORI
            _copticMap.Add(0x49, "\x2C92"); // YODA
            _copticMap.Add(0x4A, "\x3EA"); // GANGA
            _copticMap.Add(0x4B, "\x2C94"); // KABA
            _copticMap.Add(0x4C, "\x2C96"); // LOLA
            _copticMap.Add(0x4D, "\x2C98"); // MI
            _copticMap.Add(0x4E, "\x2C9A"); // NI
            _copticMap.Add(0x4F, "\x2C9E"); // O MECRON

            _copticMap.Add(0x50, "\x2CA0"); // PI
            _copticMap.Add(0x51, "\x3E6"); // KHAI
            _copticMap.Add(0x52, "\x2CA2"); // RO
            _copticMap.Add(0x53, "\x3E2"); // SHAI
            _copticMap.Add(0x54, "\x2CA6"); // TAF
            _copticMap.Add(0x55, "\x2CA8"); // EBSOLN
            _copticMap.Add(0x56, "\x2CAA"); // FI
            _copticMap.Add(0x57, "\x2CB0"); // O MEGA
            _copticMap.Add(0x58, "\x2C9C"); // EXI
            _copticMap.Add(0x59, "\x2C90"); // TETA
            _copticMap.Add(0x5A, "\x2C8C"); // ZADA
            _copticMap.Add(0x5B, "\x3ED"); // GSHIMA SMALL
            _copticMap.Add(0x5D, "\x3EF"); // TI SMALL
            _copticMap.Add(0x5E, "\x2C8B"); // SOO SMALL
            _copticMap.Add(0x5F, "_");

            _copticMap.Add(0x60, "\x2E"); // '.'
            _copticMap.Add(0x61, "\x2C81"); // ALPHA SMALL
            _copticMap.Add(0x62, "\x2C83"); // BETA SMALL
            _copticMap.Add(0x63, "\x2CA5"); // CEEMA SMALL
            _copticMap.Add(0x64, "\x2C87"); // DELTA SMALL
            _copticMap.Add(0x65, "\x2C89"); // AYYA SMALL
            _copticMap.Add(0x66, "\x3E5"); // FAY SMALL
            _copticMap.Add(0x67, "\x2C85"); // GAMMA SMALL
            _copticMap.Add(0x68, "\x3E9"); // HORI SMALL
            _copticMap.Add(0x69, "\x2C93"); // YODA SMALL
            _copticMap.Add(0x6A, "\x3EB"); // GANGA SMALL
            _copticMap.Add(0x6B, "\x2C95"); // KABA SMALL
            _copticMap.Add(0x6C, "\x2C97"); // LOLA SMALL
            _copticMap.Add(0x6D, "\x2C99"); // MI SMALL 
            _copticMap.Add(0x6E, "\x2C9B"); // NI SMALL
            _copticMap.Add(0x6F, "\x2C9F"); // O MECRON SMALL

            _copticMap.Add(0x70, "\x2CA1"); // PI SMALL
            _copticMap.Add(0x71, "\x3E7"); // KHAI SMALL
            _copticMap.Add(0x72, "\x2CA3"); // RO SMALL
            _copticMap.Add(0x73, "\x3E3"); // SHAI SMALL
            _copticMap.Add(0x74, "\x2CA7"); // TAF SMALL
            _copticMap.Add(0x75, "\x2CA9"); // EBSLON SMALL
            _copticMap.Add(0x76, "\x2CAB"); // FI SMALL
            _copticMap.Add(0x77, "\x2CB1"); // O MEGA SMALL
            _copticMap.Add(0x78, "\x2C9D"); // EXI SMALL
            _copticMap.Add(0x79, "\x2C91"); // TETA SMALL
            _copticMap.Add(0x7A, "\x2C8D"); // ZADA SMALL
            _copticMap.Add(0x7B, "\x3EC"); // GSHEMA
            _copticMap.Add(0x7D, "\x3EE"); // TI

            _copticMap.Add(0x80, "\r\n");
            _copticMap.Add(0x81, "\x222B");
            _copticMap.Add(0x82, "\x23AA");
            _copticMap.Add(0x83, "\x03ED\x2C89");
            _copticMap.Add(0x84, "\x23A9");
            _copticMap.Add(0x85, "\x23AB");
            _copticMap.Add(0x86, "\x23AD");
            _copticMap.Add(0x87, "\x03ED\x2CA9");
            _copticMap.Add(0x88, "\x03ED\x2C93");
            _copticMap.Add(0x89, "\x03ED\x2C9F");
            _copticMap.Add(0x8A, "\x23A6");
            _copticMap.Add(0x8F, "\x03ED\x2C81");

            _copticMap.Add(0x90, "\x23A7");
            _copticMap.Add(0x91, "\x23AD");
            _copticMap.Add(0x92, "\x23A8");
            _copticMap.Add(0x93, "\x23AC");
            _copticMap.Add(0x9E, "\x2194");

            _copticMap.Add(0xA0, "\x2192");
            _copticMap.Add(0xA1, "\x2190");
            _copticMap.Add(0xA2, "\x2191");
            _copticMap.Add(0xA3, "\x2193");

            _copticMap.Add(0xAC, "\x300"); // Genkem
            _copticMap.Add(0xAD, "\x301"); // Genkem acute
            _copticMap.Add(0xAE, "\x300"); // Genkem (Capital)
            _copticMap.Add(0xAF, "\x301"); // Genkem acute (Capital)

            _copticMap.Add(0xB0, "\x35E"); // Overdash
            _copticMap.Add(0xB1, "\x304"); // Macron
            _copticMap.Add(0xB2, "\x35E"); // Overdash (Capital)
            _copticMap.Add(0xB3, "\x304"); // Macron (Capital)
            _copticMap.Add(0xB4, "\x308"); // Double dots
            _copticMap.Add(0xB5, "\x300"); // Genkem

            _copticMap.Add(0xE9, "\x2C93\x304");
            _copticMap.Add(0xEA, "\x2C95\x304");
            _copticMap.Add(0xEB, "\x2C97\x304");
            _copticMap.Add(0xEC, "\x2C99\x304");
            _copticMap.Add(0xED, "\x2C9B\x304");
            _copticMap.Add(0xEE, "\x2C9D\x304");
            _copticMap.Add(0xEF, "\x2C9F\x304");

            _copticMap.Add(0xF0, "\x2CA1\x304");
            _copticMap.Add(0xF1, "\x2CA3\x304");
            _copticMap.Add(0xF2, "\x2020");
            _copticMap.Add(0xF3, "\x2A0D");
            _copticMap.Add(0xF5, ""); // Reverse Indent
            _copticMap.Add(0xFA, "/"); // Embed
            _copticMap.Add(0xFB, "|"); // Delimiter
            _copticMap.Add(0xFC, "\xA0"); // Hard space
            _copticMap.Add(0xFD, "\x200B"); // Zero width space

            // Greek Character Map
            _greekMap.Add(0x20, "\x20");
            _greekMap.Add(0x21, "\x21");
            _greekMap.Add(0x22, "\x22");
            _greekMap.Add(0x23, "\x23");
            _greekMap.Add(0x24, "\x24");
            _greekMap.Add(0x25, "\x25");
            _greekMap.Add(0x26, "\x26");
            _greekMap.Add(0x27, "\x27");
            _greekMap.Add(0x28, "\x28");
            _greekMap.Add(0x29, "\x29");
            _greekMap.Add(0x2A, "\x2A");
            _greekMap.Add(0x2B, "\x2B");
            _greekMap.Add(0x2C, "\x2C");
            _greekMap.Add(0x2D, "\x2D");
            _greekMap.Add(0x2E, "\x2E");
            _greekMap.Add(0x2F, "\x2F");

            _greekMap.Add(0x30, "0");
            _greekMap.Add(0x31, "1");
            _greekMap.Add(0x32, "2");
            _greekMap.Add(0x33, "3");
            _greekMap.Add(0x34, "4");
            _greekMap.Add(0x35, "5");
            _greekMap.Add(0x36, "6");
            _greekMap.Add(0x37, "7");
            _greekMap.Add(0x38, "8");
            _greekMap.Add(0x39, "9");
            _greekMap.Add(0x3A, "\x3A");
            _greekMap.Add(0x3B, "\x3B");
            _greekMap.Add(0x3C, "\x3C");
            _greekMap.Add(0x3D, "\x3D");
            _greekMap.Add(0x3E, "\x3E");
            _greekMap.Add(0x3F, "\x3F");

            _greekMap.Add(0x40, "\x40");
            _greekMap.Add(0x41, "\x391");
            _greekMap.Add(0x42, "\x392");
            _greekMap.Add(0x43, "\x3A9");
            _greekMap.Add(0x44, "\x394");
            _greekMap.Add(0x45, "\x395");
            _greekMap.Add(0x46, "\x3A6");
            _greekMap.Add(0x47, "\x393");
            _greekMap.Add(0x48, "\x397");
            _greekMap.Add(0x49, "\x399");
            _greekMap.Add(0x4A, "\x3A7");
            _greekMap.Add(0x4B, "\x39A");
            _greekMap.Add(0x4C, "\x39B");
            _greekMap.Add(0x4D, "\x39C");
            _greekMap.Add(0x4E, "\x39D");
            _greekMap.Add(0x4F, "\x39F");

            _greekMap.Add(0x50, "\x3A0");
            _greekMap.Add(0x51, "\x3A8");
            _greekMap.Add(0x52, "\x3A1");
            _greekMap.Add(0x53, "\x3A3");
            _greekMap.Add(0x54, "\x3A4");
            _greekMap.Add(0x55, "\x3A5");
            _greekMap.Add(0x58, "\x39E");
            _greekMap.Add(0x59, "\x398");
            _greekMap.Add(0x5A, "\x396");
            _greekMap.Add(0x5B, "\x3D9");
            _greekMap.Add(0x5C, "\\");
            _greekMap.Add(0x5D, "\x3D2");
            _greekMap.Add(0x5E, "^");
            _greekMap.Add(0x5F, "_");

            _greekMap.Add(0x60, ".");
            _greekMap.Add(0x61, "\x3B1");
            _greekMap.Add(0x62, "\x3B2");
            _greekMap.Add(0x63, "\x3C9");
            _greekMap.Add(0x64, "\x3B4");
            _greekMap.Add(0x65, "\x3B5");
            _greekMap.Add(0x66, "\x3C6");
            _greekMap.Add(0x67, "\x3B3");
            _greekMap.Add(0x68, "\x3B7");
            _greekMap.Add(0x69, "\x3B9");
            _greekMap.Add(0x6A, "\x3C7");
            _greekMap.Add(0x6B, "\x3BA");
            _greekMap.Add(0x6C, "\x3BB");
            _greekMap.Add(0x6D, "\x3BC");
            _greekMap.Add(0x6E, "\x3BD");
            _greekMap.Add(0x6F, "\x3BF");

            _greekMap.Add(0x70, "\x3C0");
            _greekMap.Add(0x71, "\x3C8");
            _greekMap.Add(0x72, "\x3C1");
            _greekMap.Add(0x73, "\x3C3");
            _greekMap.Add(0x74, "\x3C4");
            _greekMap.Add(0x75, "\x3C5");
            _greekMap.Add(0x77, "\x3C2");
            _greekMap.Add(0x78, "\x3BE");
            _greekMap.Add(0x79, "\x3B8");
            _greekMap.Add(0x7A, "\x3B6");
            _greekMap.Add(0x7B, "\x3E1");
            _greekMap.Add(0x7C, "|");
            _greekMap.Add(0x7D, "\x3DD");
            _greekMap.Add(0x7E, "~");

            _greekMap.Add(0x80, "\r\n");
            _greekMap.Add(0x81, "\x222B");
            _greekMap.Add(0x8F, "\x3B1\x345");

            _greekMap.Add(0x94, "\x3B7\x345");
            _greekMap.Add(0x95, "\x2202");
            _greekMap.Add(0x96, "\x2220");
            _greekMap.Add(0x97, "\xB1");
            _greekMap.Add(0x9D, "\x2207");
            _greekMap.Add(0x9E, "\x2194");
            _greekMap.Add(0x9F, "\x3C9\x345");

            _greekMap.Add(0xA0, "\x2192");
            _greekMap.Add(0xA1, "\x2190");
            _greekMap.Add(0xA2, "\x2191");
            _greekMap.Add(0xA3, "\x2193");
            _greekMap.Add(0xAC, "\x314");
            _greekMap.Add(0xAD, "\x313");
            _greekMap.Add(0xAE, "\x301");
            _greekMap.Add(0xAF, "\x300");

            _greekMap.Add(0xB0, "\x314\x301");
            _greekMap.Add(0xB1, "\x313\x301");
            _greekMap.Add(0xB2, "\x314\x301");
            _greekMap.Add(0xB3, "\x313\x301");
            _greekMap.Add(0xB4, "\x311");
            _greekMap.Add(0xB5, "\x308");

            _greekMap.Add(0xC5, "\x308");
            _greekMap.Add(0xC6, "\x30B");
            _greekMap.Add(0xC7, "\x311\x301");
            _greekMap.Add(0xC8, "\x311\x300");
            _greekMap.Add(0xC9, "\x30F");
            _greekMap.Add(0xCA, "\x358");
            _greekMap.Add(0xCB, "\x342");

            _greekMap.Add(0xE9, "\x2200");
            _greekMap.Add(0xEA, "\x2203");
            _greekMap.Add(0xEB, "\x220D");
            _greekMap.Add(0xEC, "\x2E2B");
            _greekMap.Add(0xED, "\xAC");
            _greekMap.Add(0xEE, "\x2227");
            _greekMap.Add(0xEF, "\x2228");

            _greekMap.Add(0xF0, "\xF7");
            _greekMap.Add(0xF1, "\xD7");
            _greekMap.Add(0xF2, "\x2020");
            _greekMap.Add(0xF3, "\x2A0D");
            _greekMap.Add(0xF5, ""); // Reverse Indent
            _greekMap.Add(0xFA, "/"); // Embed
            _greekMap.Add(0xFB, "|"); // Delimiter
            _greekMap.Add(0xFC, "\xA0"); // Hard space
            _greekMap.Add(0xFD, "\x200B"); // Zero width space
        }
    }
}

/*
Coptic Unicode Table
         
Athanathuis Hex Name
--------------------
Aa 2C80 ALPHA
Bb 2C82 BETA
Gg 2C84 GHAMA
Dd 2C86 DELTA
Ee 2C88 AYYA
<, 2C8A SOO
Zz 2C8C ZADA
Hh 2C8E HADA
Qq 2C90 TETA
Ii 2C92 YODA
Kk 2C94 KABA
Ll 2C96 LOLA
Mm 2C98 MI
Nn 2C9A NI
{[ 2C9C EXI
Oo 2C9E O
Pp 2CA0 PI
Rr 2CA2 RO
Cc 2CA4 CIMA
Tt 2CA6 TAF
Uu 2CA8 EBSELON
Vv 2CAA FI
Xx 2CAC KI
Yy 2CAE EBSI
Ww 2CB0 OMEGA
}] 03E2 SHAI
Ff 03E4 FAI
"' 03E6 KHAI
|\ 03E8 HORI
Jj 03EA GANGA
Ss 03EC GSHIMA
:; 03EE TI
-------------------
for small case, add one to hex

Other characters
. Dot
> Coptic Period (Colon)
/ Short Dash (Macron) 304
? Long Dash 305
` Jenkim: 0300 (0301 acute)
~ Dot Jenkem 0307 (0323 under dot)
!@#$ are crosses: 2719, 271A, 271B, 271C, 271D, 271E, 271F, 2720, "2725"
% Comma
^ Semicolon
& Question mark
*()- the same as ascii
_ OC of Ebshoic: 2CEA
+ Stavros: 2CE7
= Martiros: 2CE5

 */
/*
GreekC font characters
=======================
A 391 ALFA
B 392 BETA
C 3A7 CHI
D 394 DELTA
E 395 Ebslon
F 3A6 PHI
G 393 GAMA
H 397 ITA
I 399 YOTA
J ??
K 39A KABA
L 39B LAMDA
M 39C MIO
N 39D NIO
O 39F OMECRON
P 3A0 PI
Q 398 THETA
R 3A1 ROH
S 3A3 SIGMA
T 3A4 TAU
U 3A5 YEPSLON
V ??
W 3A9 OMEGA
X 39E XI
Y 3A8 EBSAY
Z 396 ZITA

Add 0x20 for small 
*/